package com.jgraves.WikiToSpeech;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.Stack;

import com.jgraves.WikiToSpeech.objects.Answer;
import com.jgraves.WikiToSpeech.objects.Dictionary;
import com.jgraves.WikiToSpeech.objects.DictionaryEntry;
import com.jgraves.WikiToSpeech.objects.Question;
import com.jgraves.WikiToSpeech.objects.Rule;
import com.jgraves.WikiToSpeech.objects.Sequence;

import android.content.Context;
import android.speech.tts.TextToSpeech;

/** Container for state of the application
 * @author johngraves
 *
 */
public class State {

	private static Sequence sequence = null;
	private static int sequenceSourceType;

	// POINTERS
	/** Pointer into sequence list for current question */
	private static Integer onQuestion = 0;
	/** Pointer into question parts lists for current answer */
	private static Integer onAnswer = 0;
	/** Pointer into color list for current color */
	private static Integer onColor = 0;

	// HISTORY
	/** Stack of questions visited for jumping back 
	 * <p> see SetOfQuestionsVisited for replay control */
	private static Stack<Integer> QuestionsVisited = new Stack<Integer>();
	private static Set<Integer> SetOfQuestionsVisited = new HashSet<Integer>();

	// MODE
	private static Boolean flashcardMode = false;
	private static Boolean silentMode = false;
	private static String needToken = ""; // This is a mode. If not blank, contains the token needed.

	private static String language = "UK";
	/** Language specific input token [input] or [ingresso], etc */
	private static String inputToken = "[input]";
	/** Language specific next token [next] or [prossimo], etc */
	private static String nextToken = "[next]";

	// DICTIONARY
	private static Dictionary dictionary = null;

	public static Sequence getSequence() {
		return sequence;
	}
	public static void setSequence(Sequence sequence) {
		State.sequence = sequence;
	}
	public static void setSequenceSourceType(int sequenceSourceType) {
		State.sequenceSourceType = sequenceSourceType;
	}
	public static int getSequenceSourceType() {
		return sequenceSourceType;
	}
	public static Integer getOnQuestion() {
		return onQuestion;
	}
	public static void setOnQuestion(Integer onQuestion) {
		State.onQuestion = onQuestion;
	}
	public static Integer getOnAnswer() {
		return onAnswer;
	}
	public static void setOnAnswer(Integer onAnswer) {
		State.onAnswer = onAnswer;
	}
	public static Integer getOnColor() {
		return onColor;
	}
	public static void setOnColor(Integer onColor) {
		State.onColor = onColor;
	}
	public static Stack<Integer> getQuestionsVisited() {
		return QuestionsVisited;
	}
	public static void pushQuestionVisited(Integer q) {
		QuestionsVisited.push(q);
	}
	public static void clearQuestionsVisited() {
		QuestionsVisited.clear();
		SetOfQuestionsVisited.clear();
	}
	public static Integer popQuestionsVisited() {
		return QuestionsVisited.pop();
	}
	public static Integer peekQuestionsVisited() {
		return QuestionsVisited.peek();
	}
	public static void setQuestionsVisited(Stack<Integer> questionsVisited) {
		QuestionsVisited = questionsVisited;
	}
	public static Set<Integer> getSetOfQuestionsVisited() {
		return SetOfQuestionsVisited;
	}
	public static void setSetOfQuestionsVisited(Set<Integer> setOfQuestionsVisited) {
		SetOfQuestionsVisited = setOfQuestionsVisited;
	}
	public static void addVisitedQuestion(Integer question) {
		QuestionsVisited.add(question);
		SetOfQuestionsVisited.add(question);
	}
	public static Integer getSequenceSize() {
		if(null!=sequence) {
			return sequence.getSize();
		} else {
			return 0;
		}
	}
	// ---------------------
	public static ArrayList<Rule> getRules() {
		return sequence.getRules();
	}	
	// ---------------------
	public static List<Question> getQuestions() {
		return sequence.getQuestions();
	}	
	// ---------------------
	public static String getQuestionLink() {
		return sequence.getQuestion(onQuestion).getQuestionLink();
	}
	// ---------------------
	public static Boolean questionLinkIsImageFile() {
		String link = sequence.getQuestion(onQuestion).getQuestionLink().toLowerCase();
		if(link.endsWith(".jpg")||link.endsWith(".png")){
			return true;
		}
		return false;
	}		
	// ---------------------
	public static Boolean hideWebView() {
		return sequence.getQuestion(onQuestion).getHideWebView();
	}	
	// ---------------------
	public static List<String> getQuestionText() {
		return sequence.getQuestion(onQuestion).getQuestionTexts();
	}	
	// ---------------------
	public static String getFirstAnswerText() {
		return sequence.getQuestion(onQuestion).getAnswer(0).getAnswerText();
	}
	// ---------------------
	public static List<Answer> getAnswers() {
		return sequence.getQuestion(onQuestion).getAnswers();
	}
	// ---------------------
	public static Boolean getQuestionHasInput() {
		Boolean hasInput = false;
		List<Answer> answers = sequence.getQuestion(onQuestion).getAnswers();
		for (Answer answer : answers) {
			if (answer.isInput()) {
				hasInput = true;
				break;
			}
		}
		return hasInput;
	}
	// ---------------------
	public static String getDestination(Integer answer) {
		return sequence.getQuestion(onQuestion).getAnswer(answer).getResponseSideLink();
	}
	// ---------------------
	/** Determine what and where input string specifies for script name and location <p>
	 * @param mDestination
	 * @return Integer code for type
	 */
	public static Integer getDestinationType(String mDestination) {
		Integer instreamType;
		if (mDestination.endsWith(".txt")) {
			instreamType = Constants.TXT;
		} else if (mDestination.endsWith(".zip")){
			if (mDestination.startsWith("http:")) {
				instreamType = Constants.ZIP_HTTP;
			} else {
				instreamType = Constants.ZIP;
			}
		} else if (0<mDestination.toLowerCase().indexOf("etherpad")){
			instreamType = Constants.HTML_ETHERPAD;
		} else {
			instreamType = Constants.HTML;
		}
		return instreamType;
	} // end getDestinationType()
	// ---------------------
	public static Boolean linkIsImageFile(Integer answer) {
		String link = sequence.getQuestion(onQuestion).getAnswer(answer).getAnswerSideLink().toLowerCase();
		if(link.endsWith(".jpg")||link.endsWith(".png")){
			return true;
		}
		return false;
	}
	// ---------------------
	public static String getLink(Integer answer) {
		return sequence.getQuestion(onQuestion).getAnswer(answer).getAnswerSideLink();
	}
	// ---------------------
	public static String getResponse(Integer answer) {
		return sequence.getQuestion(onQuestion).getAnswer(answer).getResponseText();
	}
	// ---------------------
	public static void setAnswerVisited(Integer answer) {
		sequence.getQuestion(onQuestion).getAnswer(answer).setVisited(true);
	}
	public static Boolean isFlashcardMode() {
		return flashcardMode;
	}
	public static void setFlashcardMode(Boolean flashcardMode) {
		State.flashcardMode = flashcardMode;
	}
	public static String getLanguage() {
		return language;
	}
	public static void setLanguage(String language) {
		State.language = language;
	}
	public static String getInputToken() {
		return inputToken;
	}
	public static void setInputToken(String inputToken) {
		State.inputToken = inputToken;
	}
	public static String getNextToken() {
		return nextToken;
	}
	public static void setNextToken(String nextToken) {
		State.nextToken = nextToken;
	}
	public static Boolean isSilentMode() {
		return silentMode;
	}
	public static void setSilentMode(Boolean silentMode) {
		State.silentMode = silentMode;
	}
	public static Dictionary getDictionary() {
		return dictionary;
	}
	public static void setDictionary(Dictionary dictionary) {
		State.dictionary = dictionary;
	}
	public static String getNeedToken() {
		return needToken;
	}
	public static void setNeedToken(String needToken) {
		State.needToken = needToken;
	}
	// ---------------------
	public static int backgroundColor(Context context) {
		int colorInt = 0;
		onColor += 1;
		if (4<onColor) {
			onColor = 0;
		}
		switch (onColor) {
		case 0:
			colorInt =  context.getApplicationContext().getResources().getColor(R.color.WTSDarkBlue); //0
			break;

		case 1:
			colorInt =  context.getApplicationContext().getResources().getColor(R.color.WTSTeal); //1
			break;

		case 2:
			colorInt =  context.getApplicationContext().getResources().getColor(R.color.WTSLightBlue); //2
			break;

		case 3:
			colorInt =  context.getApplicationContext().getResources().getColor(R.color.WTSGreen); //3
			break;

		case 4:
			colorInt =  context.getApplicationContext().getResources().getColor(R.color.WTSBlue);  //4
			break;
		}
		return colorInt;
	} // end changeBackgroundColor()

	// ---------------------
	public static void advanceQuestion(Integer forAnswer) {
		Question mQuestion = sequence.getQuestion(onQuestion);
		Answer mAnswer = mQuestion.getAnswer(forAnswer);
		if (0!=mAnswer.getAction()) {
			State.setOnQuestion(State.getOnQuestion() + mAnswer.getAction());
			// Allow one step past end to signal end of sequence
			State.setOnQuestion(Math.max(0,Math.min(State.getOnQuestion(), State.getSequence().getSize())));
		}
	} // end advanceQuestion()

	// ---------------------

	/** Print contents of sequence */
	public static void printSequence() {
		Integer onQuestion = 0;
		// Print results to System.out
		List<Question> questions = sequence.getQuestions();
		for (Question question : questions) {
			System.out.println("---------------------------------------------------------- Question " + onQuestion);
			String attributeName = "questionText    "; 
			if (null==question.getQuestionTexts()) {
				System.out.println(attributeName + ": <empty list>");
			} else {
				List<String> questionTexts = question.getQuestionTexts();
				for (String questionText : questionTexts) {
					System.out.println(attributeName + ": " + questionText);
				}
			}
			attributeName = "tag             "; 
			System.out.println(attributeName + ": " + question.getTag());
			attributeName = "questionLink    "; 
			System.out.println(attributeName + ": " + question.getQuestionLink());
			attributeName = "hideWebView     "; 
			System.out.println(attributeName + ": " + question.getHideWebView().toString());
			Integer onAnswer = 0;
			List<Answer> answers = question.getAnswers();
			for (Answer answer : answers) {
				System.out.println("---------------------------------------------------------- Question " + onQuestion + " Answer " + onAnswer);
				attributeName = "answerText      "; 
				System.out.println(attributeName + ": " + answer.getAnswerText());

				attributeName = "answerSideLink  "; 
				System.out.println(attributeName + ": " + answer.getAnswerSideLink());

				attributeName = "sticky          "; 
				System.out.println(attributeName + ": " + answer.isSticky());

				attributeName = "input           "; 
				System.out.println(attributeName + ": " + answer.isInput());

				attributeName = "responseText    "; 
				System.out.println(attributeName + ": " + answer.getResponseText());

				attributeName = "responseSideLink"; 
				System.out.println(attributeName + ": " + answer.getResponseSideLink());

				attributeName = "action          "; 
				System.out.println(attributeName + ": " + answer.getAction());

				attributeName = "visited         "; 
				System.out.println(attributeName + ": " + answer.isVisited());

				onAnswer += 1;
			}
			onQuestion += 1;
		}  
		// print tagMap
	} // end of printSequence()
	// ---------------------------
	public static Integer setLanguage(Context context, String newLanguage) {
		Integer result = TextToSpeech.ERROR;
		newLanguage=newLanguage.toUpperCase();
		if (newLanguage.equals("UK")) {
			WikiToSpeech.setTTSLanguage(Locale.UK); 
			inputToken = "[input]";
			nextToken = "[next]";
			//		} else if (newLanguage.equals("US")) {
			//			result = WikiToSpeech.setTTSLanguage(Locale.US); 
			//			inputToken = "[input]";
			//			nextToken = "[next]";
			//		} else if (newLanguage.equals("DE")) {
			//			result = WikiToSpeech.setTTSLanguage(Locale.GERMAN);
			//			//TODO
			//			inputToken = "[input]";
			//			nextToken = "[next]";
		} else 
			if (newLanguage.equals("IT")) {
				WikiToSpeech.setTTSLanguage(Locale.ITALIAN); 
				inputToken = "[ingresso]";
				nextToken = "[prossimo]";
			}
		if (result!=TextToSpeech.ERROR) {
			setLanguage(newLanguage);
			Library.savePreferences(context);
		}
		print(language);
		print(nextToken);
		return result;
	} // end of setLanguage

	// ---------------------

	/** Print contents of sequence */
	public static void printDictionary() {
		if ((null!=dictionary)&&(null!=dictionary.getDictionary())){
			for (DictionaryEntry de: dictionary.getDictionary()){
				print("Token:            " + de.getToken());
				print("Question to fill: " + de.getQuestionToFill());
				print("Value:            " + de.getValue());
			}
		}
	}

	// -----------------------
	public static void print(Object obj){
		System.out.println(obj.toString());
	}
}

